package geektime.spring.springbucks;

import geektime.spring.springbucks.handler.MoneyTypeHandler;
import geektime.spring.springbucks.model.Coffee;
import geektime.spring.springbucks.service.CoffeeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.RowBounds;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@EnableTransactionManagement
@SpringBootApplication
@MapperScan("geektime.spring.springbucks.mapper")
public class SpringBucksApplication implements ApplicationRunner {
//	@Autowired
//	private CoffeeMapper coffeeMapper;
	@Autowired
	private CoffeeService coffeeService;
	@Autowired
	private JedisPool jedisPool;
	@Autowired
	private JedisPoolConfig jedisPoolConfig;

	public static void main(String[] args) {
		SpringApplication.run(SpringBucksApplication.class, args);
	}

	@Bean
	@ConfigurationProperties("redis")
	public JedisPoolConfig jedisPoolConfig(){
		return new JedisPoolConfig();
	}
	@Bean(destroyMethod = "close")
	public JedisPool jedisPool(@Value("${redis.host}") String host) {
		return new JedisPool(jedisPoolConfig(), host);
	}

	@Override
	public void run(ApplicationArguments args) throws Exception {
		//增
		Coffee c = Coffee.builder().name("Cafe Americano")
				.price(Money.of(CurrencyUnit.of("CNY"), 2500.0)).build();
		int count = coffeeService.saveCoffee(c);
		log.info("Save {} Coffee: {}", count, c);
		c = Coffee.builder().name("Flat White")
				.price(Money.of(CurrencyUnit.of("CNY"), 1800.0)).build();
		count = coffeeService.saveCoffee(c);
		log.info("Save {} Coffee: {}", count, c);
		//根据主键查询
		c = coffeeService.queryById(c.getId());
		log.info("Find Coffee: {}", c);

		//根据主键批量查询
		List<Long> ids = new ArrayList();
		ids.add(1L);
		ids.add(2L);
		ids.add(3L);
		ids.add(5L);
		List<Coffee> coffees = coffeeService.queryByIdList(ids);
		log.info("Find Coffees: {}");
		for (Coffee cof: coffees) {
			log.info(cof.getId() + " :: {}", cof);
			//log.info(cof.getId() + " :: name: "+cof.getName() + " price: "+ cof.getPrice() + " createtime: " + cof.getCreateTime() + " updatetime: " + cof.getUpdateTime());
		}

		//分页查询
		coffeeService.findAllWithRowBounds(new RowBounds(1,3)).forEach(coff->log.info("findAllWithRowBounds Page(1) Coffee {} ", coff));
		coffeeService.findAllWithRowBounds(new RowBounds(3,3)).forEach(coff->log.info("findAllWithRowBounds Page(3) Coffee {} ", coff));
		log.info("===================");
		coffeeService.findAllWithParam(1,6).forEach(coff->log.info("findAllWithParam Page(1) Coffee {}", coff));

		//改
		Coffee c2 = Coffee.builder().name("Cafe Americano")
				.price(Money.of(CurrencyUnit.of("CNY"), 2500000.0)).build();
		c2.setId(6L);
		int count2 = coffeeService.updateById(c2);
		log.info("update {} Coffee: {}", count2, coffeeService.queryById(6L));

		//试试事务管理-回滚事务
		Coffee c3 = Coffee.builder().name("Cafe Americano Americano")
				.price(Money.of(CurrencyUnit.of("CNY"), 8000000.0)).build();
		c3.setId(6L);
		try {
			coffeeService.updateById2(c3);
			log.info("update Coffee: {}", coffeeService.queryById(6L));
			//throw new RollbackException();
		} catch (Exception e){
			log.info("Coffee rollback : {}", coffeeService.queryById(6L));
		}

		//试试Druid监控慢sql--filter没来得及做
		log.info("Druid:::");
		Coffee c4 = Coffee.builder().name("Cafe Americano Americano")
				.price(Money.of(CurrencyUnit.of("CNY"), 6000000.0)).build();
		c4.setId(6L);
		new Thread(() -> coffeeService.updateById3(c4)).start();
		new Thread(() -> coffeeService.updateById3(c4)).start();
		log.info("Druid::Coffee : {}", coffeeService.queryById(6L));  //查出的数据不对

		//删
		int count3 = coffeeService.deleteById(1L);
		log.info("delete count:" + count3 + "; Find delete Coffee: {}", coffeeService.queryById(1L));

		//试试redis-jedis存取数据
		log.info(jedisPoolConfig.toString());
		try (Jedis jedis = jedisPool.getResource()) {
			coffeeService.findAllWithRowBounds(new RowBounds(3,0)).forEach(coffee -> {
				jedis.hset("springbucks-menu", coffee.getName(), Long.toString(coffee.getPrice().getAmountMinorLong()));

			});
			Map<String, String> menu = jedis.hgetAll("springbucks-menu");
			log.info("Menu: {}", menu);
			String price = jedis.hget("springbucks-menu", "Cafe Americano");
			log.info("Cafe Americano - {}", Money.ofMinor(CurrencyUnit.of("USD"), Long.parseLong(price)));
		}
	}
}

